<template>
  <div>
    <div v-if="ispic">
      <el-upload action="#" :fileList="fileList" multiple listType="picture-card" :limit="filelimit" accept=".png, .jpg, .jpeg" :beforeUpload="beforeupload" :onProgress="changefileList" ref="upload" :disabled="isedit" :onExceed="handleexceed">
        <i class="el-icon-plus"></i>
        <div slot="file" slot-scope="{file}">
          <img class="el-upload-list__item-thumbnail" :src="file.url" alt />
          <span class="el-upload-list__item-actions">
            <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
              <i class="el-icon-zoom-in"></i>
            </span>
            <span class="el-upload-list__item-delete" @click="handleDownload(file)" v-if="isdowload">
              <i class="el-icon-download"></i>
            </span>
            <span class="el-upload-list__item-delete" @click="handleRemove(file)" v-if="!isedit">
              <i class="el-icon-delete"></i>
            </span>
          </span>
        </div>
      </el-upload>
      <el-dialog :visible.sync="dialogVisible" appendToBody>
        <img width="100%" :src="dialogImageUrl" alt />
      </el-dialog>
    </div>
    <div v-else>
      <el-upload action :fileList="fileList" multiple :limit="filelimit" :onExceed="handleexceed" :beforeUpload="beforeupload" :onPreview="handlePictureCardPreview2" :onProgress="changefileList" ref="upload" :onRemove="handleRemove" :beforeRemove="beforeremove">
        <el-button size="small" type="primary" v-if="!isedit">点击上传</el-button>
        <!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件，且不超过500kb</div> -->
      </el-upload>
    </div>
  </div>
</template>

<script>
import SparkMD5 from 'spark-md5';

const baseUrl = 'http://oa.jbrsys.com:5000';
let chunkSize = 1 * 1024 * 1024;

let file = null;
let fileSize = 0;
let chunks = 5;
let blobSlice;
let currentChunk = 0;
let fileReader;

export default {
  props: {
    ispic: Boolean,
    filelimit: Number,
    isedit: Boolean,
    filelink: Array,
    isdowload: Boolean,
  },
  data () {
    return {
      ts: this.newStore(),
      fileList: [],
      dialogImageUrl: '',
      dialogVisible: false,
    };
  },
  mounted () {
    if (this.isedit) {
      const a = document.getElementsByClassName('el-upload--picture-card');
      if (a.length > 0) {
        for (let i = 0; i < a.length; i += 1) {
          a[i].style.display = 'none';
        }
      }
    }
    this.fileList = this.filelink;
  },
  methods: {
    // eslint-disable-next-line consistent-return
    beforeremove () {
      if (this.isedit) {
        this.$message({
          message: '当前状态不可删除',
          type: 'error',
        });
        return false;
      }
    },
    handleDownload (file1) {
      const elt = document.createElement('a');
      elt.setAttribute('href', file1.url);
      elt.setAttribute('target', '_blank');
      elt.setAttribute('download', file1.name);
      elt.style.display = 'none';
      // console.log(elt);

      document.body.appendChild(elt);
      elt.click();
      document.body.removeChild(elt);
    },
    handleexceed () {
      this.$message({
        message: '已超出上传限制，请先删除',
        type: 'error',
      });
    },
    // eslint-disable-next-line consistent-return
    beforeupload (file2) {
      for (let i = 0; i < this.fileList.length; i += 1) {
        if (this.fileList[i].name == file2.name) {
          this.$message({
            message: '请勿重复提交图片或文件',
            type: 'error',
          });
          return false;
        }
      }
    },
    handleRemove (file2) {
      // console.log(this.fileList.indexOf(file2.name));
      for (let i = 0; i < this.fileList.length; i += 1) {
        if (file2.name == this.fileList[i].name) {
          this.fileList.splice(i, 1);
        }
      }
      //console.log(this.fileList, 'this.fileList');

    },
    changePic (url, name) {
      const a = {};
      a.name = name;
      a.url = url;
      this.fileList.push(a);
      this.$emit('update:filelink', this.fileList);
    },
    handlePictureCardPreview (file1) {
      this.dialogImageUrl = file1.url;
      this.dialogVisible = true;
    },
    handlePictureCardPreview2 (file1) {
      const elt = document.createElement('a');
      elt.setAttribute('href', file1.url);
      elt.setAttribute('download', file1.name);
      elt.setAttribute('target', '_blank');
      elt.style.display = 'none';
      document.body.appendChild(elt);
      elt.click();
      document.body.removeChild(elt);
    },

    changefileList (event, file1) {
      file = file1.raw;
      fileSize = Math.floor(file.size);
      this.responseChange(file);
    },
    async upload (i, fileMd5Value, pchunks) {
      return new Promise((resolve) => {
        // 构造一个表单，FormData是HTML5新增的
        const end =
          (i + 1) * chunkSize >= file.size ? file.size : (i + 1) * chunkSize;
        const form = new FormData();
        form.append('data', file.slice(i * chunkSize, end)); // file对象的slice方法用于切出文件的一部分
        form.append('total', pchunks); // 总片数
        form.append('index', i); // 当前是第几片
        form.append('fileMd5Value', fileMd5Value);
        this.spost(this.ts, `${baseUrl}/upload`, form)
          .then((ts) => {
            resolve(ts.d.desc);
          })
          .catch((ts) => {
            resolve(ts.d.desc);
          });
      });
    },
    async checkAndUploadChunk (fileMd5Value, chunkList) {
      return new Promise((resolve) => {
        chunks = Math.ceil(fileSize / chunkSize);
        const promiselist = [];

        for (let i = 0; i < chunks; i += 1) {
          const exit = chunkList.indexOf(`${i}`) > -1;
          // 如果已经存在, 则不用再上传当前块
          if (!exit) {
            promiselist.push(this.upload(i, fileMd5Value, chunks));
          }
        }
        Promise.all(promiselist).then(() => {
          resolve();
        });
      });
    },

    async checkFileMD5 (fileName, fileMd5Value) {
      return new Promise((resolve) => {
        const url = `${baseUrl}/check/file`;

        this.sget(this.ts, url, { fileName, fileMd5Value }).then((ts) => {
          resolve(ts.d);
        });
      }).catch((reject) => {
        reject();
      });
    },

    notifyServer (fileMd5Value) {
      const url = `${baseUrl}/merge?md5=${fileMd5Value}&fileName=${file.name}&size=${file.size}`;
      this.sget(this.ts, url, {}).then((ts) => {
        const pic = `${baseUrl}/nodeServer/uploads/${ts.d.fname}`;
        this.changePic(pic, file.name);
      });
    },

    loadNext () {
      const start = currentChunk * chunkSize;
      const end =
        start + chunkSize >= file.size ? file.size : start + chunkSize;

      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    },
    async md5File (pfile) {
      return new Promise((resolve) => {
        blobSlice =
          File.prototype.slice ||
          File.prototype.mozSlice ||
          File.prototype.webkitSlice;

        chunkSize = pfile.size / chunks;

        currentChunk = 0;
        const spark = new SparkMD5.ArrayBuffer();
        fileReader = new FileReader();

        fileReader.onload = (e) => {
          spark.append(e.target.result);

          currentChunk += 1;

          if (currentChunk < chunks) {
            this.loadNext();
          } else {
            const result = spark.end();
            resolve(result);
          }
        };

        fileReader.onerror = () => {
          console.warn('oops, something went wrong.');
        };

        this.loadNext();
      }).catch((reject) => {
        reject();
      });
    },

    async responseChange (pfile) {
      // 第一步：按照 修改时间+文件名称+最后修改时间-->MD5
      // 显示文件校验进度
      const fileMd5Value = await this.md5File(pfile);

      const fileName = fileMd5Value.concat(
        '.',
        pfile.name.split('.')[pfile.name.split('.').length - 1],
      );
      // 第二步：校验文件的MD5
      const result = await this.checkFileMD5(fileName, fileMd5Value);
      console.log(result, 'reslt');

      // 如果文件已存在, 就秒传
      if (result.file) {
        const pic = `${baseUrl}/nodeServer/uploads/${fileName}`;
        this.changePic(pic, pfile.name);
        return;
      }
      // 显示文件上传进度

      this.checkAndUploadChunk(fileMd5Value, result.chunkList).then(() => {
        this.notifyServer(fileMd5Value);
      });

      // 第四步: 通知服务器所有分片已上传完成
    },
    verificationPicFile (pfile) {
      const fileTypes = ['.jpg', '.png'];
      const filePath = pfile.value;
      // 当括号里面的值为0、空字符、false 、null 、undefined的时候就相当于false
      if (filePath) {
        let isNext = false;
        const fileEnd = filePath.substring(filePath.indexOf('.'));
        for (let i = 0; i < fileTypes.length; i += 1) {
          if (fileTypes[i] === fileEnd) {
            isNext = true;
            break;
          }
        }
        if (!isNext) {
          alert('不接受此文件类型');
          pfile.value = '';
          return false;
        }
      } else {
        return false;
      }
      return true;
    },
  },
};
</script>

<style>
.el-upload-list__item div {
  text-align: center;
}
</style>
